package PortReplicator2 () where

import FIFO
import Counter

import AsyncROM

type Adr = (Bit 32)
type Dta = (Bit 32)

type Tag = (Bit 2)

type ROM lat = AsyncROM lat Adr Dta

mk3ROMports :: (Add lat 1 lat1, Log lat1 loglat1)
            => ROM lat -> Module (ROM lat1, ROM lat1, ROM lat1)
mk3ROMports rom =
  module
    tags :: FIFO Tag <- mkSizedFIFO (valueOf lat)

    let mkPort :: (Add lat 1 lat1) => Tag -> Module (ROM lat1)
        mkPort i =
          module
            out :: FIFO Dta <- mkSizedFIFO (valueOf lat)
            cnt :: Counter loglat1 <- mkCounter (fromInteger (valueOf lat))
            rules
              when tags.first == i
                ==> action tags.deq
                           rom.ack
                           out.enq rom.result
            interface
              read a = action rom.read a
                              tags.enq i
                              cnt.down
                       when cnt.value > 0
              result = out.first
              ack = action out.deq
                           cnt.up

    port0 :: ROM lat1 <- mkPort 0
    port1 :: ROM lat1 <- mkPort 1
    port2 :: ROM lat1 <- mkPort 2
    interface (port0, port1, port2)


